package cn.xsly.basic.service.impl;

import cn.xsly.basic.constant.VerifyCodeConstant;
import cn.xsly.basic.dto.SmsCodeDto;
import cn.xsly.basic.exception.BusinessException;
import cn.xsly.basic.service.IVerifyService;
import cn.xsly.basic.util.StrUtils;
import cn.xsly.basic.util.VerifyCodeUtils;
import cn.xsly.user.domain.User;
import cn.xsly.user.mapper.UserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;
@Service
public class VerifyServiceImpl implements IVerifyService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String getImgCode(String key) {
        //1.获取随机验证码
        String code = StrUtils.getComplexRandomString(4);
        //2.保存到redis - 并设置5分钟过期
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //3.获取图形验证码编码的之后的字符串
        String base64Str = VerifyCodeUtils.verifyCode(115, 40, code);
        return base64Str;
    }

    @Override
    public void sendSmsCode(SmsCodeDto smsCodeDto) {
        /*String phone = smsCodeDto.getPhone();
        String imageCode = smsCodeDto.getImageCode();
        String imageCodeKey = smsCodeDto.getImageCodeKey();
        //1.校验 - 空值校验
        if(StringUtils.isEmpty(phone)||StringUtils.isEmpty(imageCode)){
            throw new BusinessException("电话或图片验证码为空");
        }
        //2.校验 - 图片验证码校验
        //2.1.图片验证码是否过期
        //2.2.图片验证码是否正确
        Object key = redisTemplate.opsForValue().get(imageCodeKey);
        if(key==null){

        }
        Long s = Long.valueOf(time.toString().split(":")[1]);


        //3.校验 - 手机号是否被注册 - 查询t_user表

        //4.判断原来的验证码是否有效【3分钟过期 - redis】，从redis是否能拿到通过key【register:18708146200】
        //4.1.如果拿到了，表示有效,继续判断是否过了1分钟重发时间 value【9527:14688777777711】
        //4.1.1.如果没有过，就不应该再发，提示错误 - 请勿重发验证码
        //4.1.2.如果过了，就使用上次的验证码，但是要刷新过期时间【重新添加resis，用新的时间戳】
        //4.2.如果没有拿到，表示验证码过期了
        //4.2.1.重新生成验证码，并添加到redis
        //5.调用短信接口发送短信*/

        //1.校验 - 空值校验
        String phone = smsCodeDto.getPhone();
        String imageCode = smsCodeDto.getImageCode();
        String imageCodeKey = smsCodeDto.getImageCodeKey();
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号不可为空");
        }
        if(StringUtils.isEmpty(imageCode)){
            throw new BusinessException("图片验证码不能为空");
        }
        if(StringUtils.isEmpty(imageCodeKey)){
            throw new BusinessException("请刷新页面重新获取图片验证码");
        }

        //3.校验 - 手机号是否被注册
        User user = userMapper.loadByPhone(phone);
        if(user != null){
            throw new BusinessException("该手机已经注册，请直接登录!");
        }
        //2.校验 - 图片验证码校验
        //2.1.图片验证码是否过期
        Object imgObj = redisTemplate.opsForValue().get(imageCodeKey);
        if(imgObj == null ){
            throw new BusinessException("图片验证码过期");
        }
        //2.2.图片验证码是否正确
        if(!imgObj.toString().equalsIgnoreCase(imageCode)){
            throw new BusinessException("错误的图片验证码");
        }



        //redis存值格式：key[register:18708146200] : value[code:time]
        //从redis中获取手机验证码
        Object smsObj = redisTemplate.opsForValue().get(VerifyCodeConstant.REGISTER_CODE_PREFIX + phone);
        String smsCode = null;
        if(smsObj== null){//没有验证码=第一次获取或是手机验证码过期
            smsCode=StrUtils.getRandomString(6);
        }else{
            //有验证码
            long nowTime=System.currentTimeMillis();
            String oldTimeTemp=smsObj.toString().split(":")[1];
            long oldTime=Long.parseLong(oldTimeTemp);
            if((nowTime-oldTime)<1*60*1000){
                throw new BusinessException("操作过于频繁，请稍后重试");
            }else {
                smsCode=smsObj.toString().split(":")[0];
            }
        }
        //将验证码数据添加到redis
        redisTemplate.opsForValue().set(VerifyCodeConstant.REGISTER_CODE_PREFIX + phone,
                smsCode + ":" + System.currentTimeMillis(),3, TimeUnit.MINUTES);//存3分钟
        //发短信
        //SmsUtil.sendSms(phone, "你的验证码为：" + code + "，请在3分钟之内使用!" );  //有次数
        System.out.println("你的验证码为：" + smsCode + "，请在3分钟之内使用!");//可以这样测试
    }
    @Override
    public void binderSmsCode(SmsCodeDto smsDto) {
        String phone = smsDto.getPhone();
        //1.校验
        //a.非空校验 - 3个
        if(StringUtils.isEmpty(phone)){
            throw new BusinessException("手机号码不能为空");
        }
        //三：校验：手机号码是否绑定过微信
        User user = userMapper.findWxUserByPhone(phone);
        if(user != null){//根据手机号码查到了 = 手机已经注册
            throw new BusinessException("该号码已经绑定过微信，请直接登陆!!!");
        }
        //2.生成手机验证码
        //redis保存手机验证码：register:18856566636 - 9527:156336655555
        //a.从redis中获取手机验证码 - 进行判断
        Object smsObj = redisTemplate.opsForValue().get(VerifyCodeConstant.BINDER_CODE_PREFIX + phone); //9527:156336655555
        String smsCode = null;
        if(smsObj == null){
            //a1.如果没有 = 第一次获取或手机验证码过期 -> 重新调用StrUtils创建新的手机验证码
            smsCode = StrUtils.getRandomString(6);
        }else{
            //a2.如果有 = 手机验证码过期没有过期 -> 判断重发时间【时间戳相减与1分钟】
            long nowTime = System.currentTimeMillis();
            String oldTimeTemp = smsObj.toString().split(":")[1];
            long oldTime = Long.parseLong(oldTimeTemp);
            if((nowTime-oldTime)<1*60*1000){//重复发送短信验证码
                //a21.如果没有过重发时间 -> 抛业务异常【操作过于频繁，请稍后再试】
                throw new BusinessException("操作过于频繁，请稍后再试");
            }else{
                //a22.如果过了重发时间 -> 就使用以前的验证码
                smsCode = smsObj.toString().split(":")[0];
            }
        }
        //3.手机验证码保存到redis - 要不要刷新过期时间？[保存到redis要不要再次设置3分钟有效]
        redisTemplate.opsForValue().set(VerifyCodeConstant.BINDER_CODE_PREFIX+phone,
                smsCode+":"+System.currentTimeMillis(),3,TimeUnit.MINUTES);
        //4.调用工具类发送短信
        //SmsUtils.sendSms(phone,"你的验证码是：" + smsCode+",请在3分钟内使用!!!");
        System.out.println("你的验证码是：" + smsCode+",请在3分钟内使用!!!");
    }

}
